package com.ampaiva.pattern.observer;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.WeakHashMap;

public abstract aspect ObserverPattern {
    public interface Subject {
    }

    public interface Observer {
    }

    private WeakHashMap<Subject, List<Observer>> soHash = new WeakHashMap<Subject, List<Observer>>();

    private List<Observer> getObservers(Subject s) {
        List<Observer> observers = (List<Observer>) soHash.get(s);
        if (observers == null) {
            observers = new LinkedList<Observer>();
            soHash.put(s, observers);
        }
        return observers;
    }

    public void addObserver(Subject s, Observer o) {
        getObservers(s).add(o);
        updateObs(s, o);
    }

    public void removeObserver(Subject s, Observer o) {
        getObservers(s).remove(o);
    }

    public abstract pointcut subjectChange(Subject s);

    public abstract void updateObs(Subject s, Observer o);

    after(Subject s): subjectChange(s) {
        Iterator<Observer> it = getObservers(s).iterator();
        while (it.hasNext()) {
            Observer o = (Observer) it.next();
            updateObs(s, o);
        }
    }
}
